package com.client.controller.auth;

import com.client.entity.B_client;
import com.client.mapper.MessageDao;
import com.client.mapper.PassAuthorDao;
import com.client.service.ExchangeService;
import com.client.service.KeyService;
import com.client.service.MessageService;
import com.client.service.MigrationService;
import com.client.sm9.gm.sm9.G1KeyPair;
import com.client.sm9.gm.sm9.ResultKeyExchange;
import com.client.sm9.gm.sm9.SM9Utils;
import com.client.utils.MessageUtils;
import com.client.utils.UDPUtil;
import com.client.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Component
//计算迁移消息处理
public class Migration {
    @Autowired
    UDPUtil udp;
    @Autowired
    MigrationService migrationService;
    @Autowired
    PassAuthorDao passAuthorDao;
    @Autowired
    KeyService keyService;
    @Autowired
    MessageService messageService;
    @Autowired
    ExchangeService exchangeService;
    @Autowired
    MessageDao messageDao;

    @Value("${udp.receive}")
    private Integer port;

    @ServiceActivator(inputChannel = "Encrypt-result")
    public void EncryptHandler(Map<String, Object> map, @Headers Map<String, Object> headers) {


//        String uid =  map.get("uid").toString();
//        String id = messageDao.queryByUID(uid);
        B_client client = messageService.getClient((UUID) map.get("uid"));
        byte[] result = (byte[]) map.get("result");
        udp.send(client.getGoal_ip(), client.getGoal_port(), result);
        addMessage(client, result, "认证",map);
    }

    @ServiceActivator(inputChannel = "Decrypt-result", outputChannel = "decrypt-result")
    public Map<String, Object> DecryptHandler(Map<String, Object> map, @Headers Map<String, Object> headers) {
//        deleteMessage(map,headers);

        byte[] result = (byte[]) map.get("result");
        try {
            Map<String, Object> body = Utils.getObjectMapFromByte(result);

//            Date time = MessageUtils.getNowTime();
//            MessageService.deleteMessage(body.get("uid").toString());
//            messageDao.add((String) body.get("id"), keyService.getId(),(String) headers.get("ip_address"),
//                    0, body.get("uid").toString(), null,
//                    0, (String) body.get("type"), new Timestamp(time.getTime()));

            return body;
        } catch (Exception e) {
            log.info("Map反序列化失败");
        }
        return null;
    }

    @ServiceActivator(inputChannel = "Sign-result")
    public void SignHandler(Map<String, Object> map, @Headers Map<String, Object> headers) {

    }

    @ServiceActivator(inputChannel = "Verify-result")
    public void VerifyHandler(Map<String, Object> map, @Headers Map<String, Object> headers) {

    }

    @ServiceActivator(inputChannel = "Exchange1-result")
    public void Exchange1Handler(Map<String, Object> map, @Headers Map<String, Object> headers) {


        String uid = map.get("uid").toString();
        String id = messageDao.queryByUID(uid, keyService.getId());
        B_client client = messageService.getClient(id);
        byte[] result = (byte[]) map.get("result");
        G1KeyPair g1KeyPair = Utils.deserializeG1KeyPair(result);


        if (client.isSponsor()) {//发起者
            client.setMyKeyPair(g1KeyPair);
            client.setExchang_flag(1);
            byte[] body_b = exchangeService.exchange1(client);
            udp.send(client.getGoal_ip(), client.getGoal_port(), body_b);
            addMessage(client, body_b, "密钥交换1",map);
        } else {//接收者
            int length = 16;    //密钥长度
            client.setMyKeyPair(g1KeyPair);
            migrationService.Exchange2(client.getGoal_id(), client.getUid(), client.isSponsor(), length,
                    g1KeyPair, client.getGoal_R());
        }


    }

    @ServiceActivator(inputChannel = "Exchange2-result")
    public void Exchange2Handler(Map<String, Object> map, @Headers Map<String, Object> headers) {
        String uid = map.get("uid").toString();
        //

        String id = messageDao.queryByUID(uid, keyService.getId());
        B_client client = messageService.getClient(id);
        byte[] result = (byte[]) map.get("result");
        ResultKeyExchange resultKeyExchange = Utils.deserializeResultKeyExchange(result);

        client.setResultKeyExchange(resultKeyExchange);
        if (!client.isSponsor()) {
            client.setMy_S(resultKeyExchange.getSA2());
            client.setK(resultKeyExchange.getSK());
            //接收者
            byte[] body_b = exchangeService.exchange2(client);

            //发送udp包
            udp.send(client.getGoal_ip(), client.getGoal_port(), body_b);
            addMessage(client, body_b, "密钥交换2",map);
            //修改状态
            client.setExchang_flag(2);

        } else {
            //发送者
            client.setMy_S(resultKeyExchange.getSB1());
            client.setK(resultKeyExchange.getSK());
            //现在已知SB\S2\K与SA,将Rb与SB发给对方

            if (!SM9Utils.byteEqual(client.getGoal_S(), client.getMy_S())) {
                client.setExchang_flag(-1);
                log.info("[" + id + "]的密钥交换请求失败：goal_S与my_S不相同！");
                return;
            } else {
                log.info("[" + id + "]的密钥交换请求成功！密钥为：" + SM9Utils.toHexPureString(client.getK()));
            }
            byte[] body_b = exchangeService.exchange3(client);

            //发送udp包
            udp.send(client.getGoal_ip(), client.getGoal_port(), body_b);
            addMessage(client, body_b, "密钥交换3",map);

            //修改状态
            client.setExchang_flag(3);
        }
    }

    public void addMessage(B_client client, byte[] msg, String type,Map<String, Object> map) {
        Date time = MessageUtils.getNowTime();
        MessageService.addMessage(client.getUid().toString(), client.getGoal_ip(), client.getGoal_port(), msg,
                time, 8, 30);
        messageDao.add(client.getGoal_id(), keyService.getId(), client.getGoal_ip(), client.getGoal_port(), client.getUid().toString(),
                null, 1, type, new Timestamp(time.getTime()));
    }

}
